Completed
Push — master ( 2f8415...e6e0b0 )
by Rain
02:22
created

Cmd.js ➔ initGlass   B

Complexity

Conditions 5
Paths 8

Size

Total Lines 15

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 1 Features 0
Metric Value
cc 5
c 1
b 1
f 0
nc 8
nop 0
dl 0
loc 15
rs 8.8571
1
2
import window from 'window';
3
import $ from '$';
4
import _ from '_';
5
import ko from 'ko';
6
import {$html, $body} from 'Common/Globals';
7
import {EventKeyCode, Magics} from 'Common/Enums';
8
import {trim, inArray, changeTheme} from 'Common/Utils';
9
import {reload as translatorReload} from 'Common/Translator';
10
11
import * as Settings from 'Storage/Settings';
12
13
import ThemeStore from 'Stores/Theme';
14
import LanguageStore from 'Stores/Language';
15
16
let
17
	cmdDom = null,
18
	contoller = null;
19
20
/**
21
 * @params {string} cmd
22
 * @returns {string}
23
 */
24
function cmdError(cmd) {
25
	return require('Html/Cmds/Error.html').replace('{{ cmd }}', cmd);
26
}
27
28
/**
29
 * @returns {string}
30
 */
31
function cmdClear(dom) {
32
	dom.find('.rl-cmd-history-data').empty();
33
	return '';
34
}
35
36
/**
37
 * @returns {string}
38
 */
39
function cmdHelp(cmds) {
40
	return require('Html/Cmds/Help.html').replace('{{ commands }}', cmds.join(' '));
41
}
42
43
/**
44
 * @returns {void}
45
 */
46
function initGlass() {
47
	let state = null;
48
	try {
49
		if (window.localStorage && window.localStorage.setItem)
50
		{
51
			state = '1' === '' + window.localStorage.getItem('rl-labs-glass');
52
		}
53
	}
54
	catch (e) {} // eslint-disable-line no-empty
55
56
	if (null !== state)
57
	{
58
		$html.toggleClass('glass', !!state);
59
	}
60
}
61
62
/**
63
 * @returns {string}
64
 */
65
function cmdGlass() {
66
	const state = !$html.hasClass('glass');
67
68
	try {
69
		if (window.localStorage && window.localStorage.setItem)
70
		{
71
			window.localStorage.setItem('rl-labs-glass', state ? '1' : '0');
72
		}
73
	}
74
	catch (e) {} // eslint-disable-line no-empty
75
76
	$html.toggleClass('glass', state);
77
	return '';
78
}
79
80
/**
81
 * @returns {string}
82
 */
83
function cmdTheme(param, themes) {
84
	if (param && -1 < inArray(param, themes))
85
	{
86
		changeTheme(param);
87
		return '';
88
	}
89
	return require('Html/Cmds/ThemeEmpty.html').replace('{{ themes }}', themes.join(', '));
90
}
91
92
/**
93
 * @returns {string}
94
 */
95
function cmdLang(param, isAdmin, langs) {
96
	if (param && -1 < inArray(param, langs))
97
	{
98
		translatorReload(isAdmin, param);
99
		return '';
100
	}
101
	return require('Html/Cmds/LangEmpty.html').replace('{{ langs }}', langs.join(', '));
102
}
103
104
/**
105
 * @returns {string}
106
 */
107
function cmdVersion() {
108
	return require('Html/Cmds/Version.html').replace('{{ version }}',
109
		Settings.appSettingsGet('version') + ' (' + Settings.appSettingsGet('appVersionType') + ')');
110
}
111
112
class CmdContoller
113
{
114
	dom = null;
115
116
	opened = ko.observable(false);
117
	cmd = ko.observable('');
118
	focused = ko.observable(false);
119
120
	themes = ThemeStore.themes;
121
122
	cmdHistory = [];
123
	cmdHistoryShift = 0;
124
125
	cmdHelper = ko.observable('');
126
127
	cmds = ['help', 'version', 'glass', 'clear', 'theme', 'lang'];
128
	cmdsWithParameters = ['theme', 'lang'];
129
130
	isAdmin = false;
131
132
	constructor(dom)
133
	{
134
		this.dom = dom;
135
		this.isAdmin = !!Settings.appSettingsGet('admin');
136
	}
137
138
	runCmd(cmd, params, isTab) {
139
140
		let
141
			result = '',
142
			values = null;
143
144
		this.cmdHelper('');
145
146
		if (isTab)
147
		{
148
			switch (cmd) {
149
				case 'lang':
150
					values = (this.isAdmin ? LanguageStore.languagesAdmin() : LanguageStore.languages())
151
						.filter((line) => 0 === line.lastIndexOf(params, 0));
152
					break;
153
				case 'theme':
154
					values = ThemeStore.themes().filter((line) => 0 === line.lastIndexOf(params, 0));
155
					break;
156
				default:
157
					break;
158
			}
159
160
			if (cmd && values)
161
			{
162
				if (1 === values.length && values[0])
163
				{
164
					this.cmd(cmd + ' ' + values[0]);
165
				}
166
				else if (1 < values.length && values[0] && values[1])
167
				{
168
					let
169
						sub = '',
170
						index = 0;
171
172
					const
173
						list = values[0].split(''),
174
						len = list.length;
175
176
					for (; index < len; index++)
177
					{
178
						if (values[1][index] === list[index])
179
						{
180
							sub += list[index];
181
						}
182
						else
183
						{
184
							break;
185
						}
186
					}
187
188
					if (sub)
189
					{
190
						this.cmdHelper('[' + values.join(', ') + ']');
191
						this.cmd(cmd + ' ' + sub);
192
					}
193
				}
194
			}
195
196
			return '';
197
		}
198
199
		switch (cmd) {
200
			case 'hi':
201
				result = 'hello';
202
				break;
203
			case '?':
204
			case 'ls':
205
			case 'help':
206
				result = cmdHelp(this.cmds);
207
				break;
208
			case 'glass':
209
				result = cmdGlass();
210
				break;
211
			case 'v':
212
			case 'version':
213
				result = cmdVersion();
214
				break;
215
			case 'clear':
216
				result = cmdClear(this.dom);
217
				break;
218
			case 'theme':
219
				result = cmdTheme(params, ThemeStore.themes());
220
				break;
221
			case 'lang':
222
				result = cmdLang(params, this.isAdmin, this.isAdmin ? LanguageStore.languagesAdmin() : LanguageStore.languages());
223
				break;
224
			default:
225
				result = cmdError(cmd);
226
				break;
227
		}
228
229
		return result;
230
	}
231
232
	onCmd(isTab) {
233
		const
234
			cmdLine = this.cmd().replace(/[\s]+/, ' '),
235
			cmdParts = trim(cmdLine).replace().split(/[\s]+/),
236
			cmd = cmdParts.shift();
237
238
		if ('' === trim(cmdLine))
239
		{
240
			return false;
241
		}
242
243
		if (isTab)
244
		{
245
			if (-1 < inArray(cmd, this.cmds))
246
			{
247
				const result = this.runCmd(cmd, cmdParts.join(' '), true);
248
				if (result)
249
				{
250
					this.cmd(result);
251
				}
252
			}
253
			else
254
			{
255
				const values = this.cmds.filter((line) => line !== cmd && 0 === line.lastIndexOf(cmd, 0));
256
				if (1 === values.length && values[0])
257
				{
258
					this.cmd(values[0] + (-1 < inArray(values[0], this.cmdsWithParameters) ? ' ' : ''));
259
				}
260
			}
261
		}
262
		else
263
		{
264
			this.cmdHistory.unshift(cmdLine);
265
			this.cmdHistory = _.uniq(this.cmdHistory);
266
			this.cmdHistoryShift = 0;
267
268
			const
269
				result = this.runCmd(cmd, cmdParts.join(' '), false),
270
				h = this.dom.find('.rl-cmd-history-data');
271
272
			if (h && h[0])
273
			{
274
				h.append($('<div></div>').html(require('Html/Cmds/Main.html').replace('{{ cmd }}', cmdLine)));
275
				if (result)
276
				{
277
					h.append($('<div></div>').html(result));
278
				}
279
280
				_.delay(() => {
281
					this.dom.find('.rl-cmd-history').scrollTop(h.height());
282
				}, 50);
283
			}
284
		}
285
286
		return true;
287
	}
288
289
	onEsc() {
290
		this.opened(false);
291
		return false;
292
	}
293
294
	onTab() {
295
		this.onCmd(true);
296
		return false;
297
	}
298
299
	onEnter() {
300
		this.onCmd(false);
301
		this.cmd('');
302
		return false;
303
	}
304
305
	onKeyDown(event) {
306
		if (event && event.keyCode &&
307
			!event.metaKey && !event.ctrlKey && !event.shiftKey && 0 < this.cmdHistory.length)
308
		{
309
			const code = window.parseInt(event.keyCode, 10);
310
			if (EventKeyCode.Up === code || EventKeyCode.Down === code)
311
			{
312
				if (this.cmdHistory[this.cmdHistoryShift])
313
				{
314
					this.cmd(this.cmdHistory[this.cmdHistoryShift]);
315
					if (EventKeyCode.Up === code)
316
					{
317
						this.cmdHistoryShift += 1;
318
					}
319
					else if (EventKeyCode.Down === code)
320
					{
321
						this.cmdHistoryShift -= 1;
322
					}
323
				}
324
				else
325
				{
326
					this.cmdHistoryShift = 0;
327
				}
328
329
				return false;
330
			}
331
		}
332
333
		return true;
334
	}
335
}
336
337
/**
338
 * @returns {void}
339
 */
340
export function bind(dom)
341
{
342
	if (!contoller)
343
	{
344
		contoller = new CmdContoller(dom);
345
346
		ko.applyBindingAccessorsToNode(dom[0], {
347
			translatorInit: true,
348
			template: () => ({name: 'Cmd'})
349
		}, contoller);
350
	}
351
}
352
353
/**
354
 * @returns {void}
355
 */
356
function init()
357
{
358
	if (null === cmdDom)
359
	{
360
		cmdDom = $('<div></div>');
361
		cmdDom.appendTo($body);
362
363
		bind(cmdDom);
364
	}
365
}
366
367
/**
368
 * @returns {void}
369
 */
370
export function toggle()
371
{
372
	if (Settings.appSettingsGet('allowCmdInterface'))
373
	{
374
		init();
375
376
		_.delay(() => {
377
			if (contoller)
378
			{
379
				contoller.opened(!contoller.opened());
380
				if (contoller.opened())
381
				{
382
					_.delay(() => {
383
						if (contoller && contoller.focused)
384
						{
385
							contoller.focused(true);
386
						}
387
					}, Magics.Time50ms);
388
				}
389
			}
390
		}, Magics.Time50ms);
391
	}
392
}
393
394
// init
395
initGlass();
396